package com.broker.provider.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import me.send.broker.entity.BatchWithdrawOrder;
import me.send.broker.entity.BrokerWalletLog;
import me.send.broker.entity.WithdrawOrder;
import me.send.broker.mapper.BrokerMapper;
import me.send.broker.pojo.WithdrawRecord;
import me.send.broker.pojo.WithdrawRecordBean;
import me.send.broker.service.MessageService;
import me.send.broker.service.WalletService;
import me.send.business.base.jpush.JPush;
import me.send.broker.cons.MessageCons;
import me.send.broker.cons.OrderCons;
import me.send.broker.entity.Message;
import me.send.framework.util.HelperUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cn.jpush.api.JPushClient;

import com.broker.provider.base.BaseService;
public class WalletServiceImpl extends BaseService implements WalletService {
	private final static Logger logger = LoggerFactory
			.getLogger(WalletServiceImpl.class.getName());
	@Autowired
	protected MessageService messageService;
	@Autowired
	BrokerMapper brokerMapper;
	public List<Double> getBalance(int popid) {
		Map<String, Object> map = walletMapper.getBalance(popid);
		if (map == null) {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Map<String, Object> temp = new HashMap<String, Object>();
			temp.put("popid", popid);
			temp.put("date", sdf.format(new Date()));
			walletMapper.addBrokerWallet(temp);
			map = walletMapper.getBalance(popid);
		}
		List<Double> result = new ArrayList<Double>();
		result.add(Double.parseDouble(map.get("purchaseBalance").toString()));
		result.add(Double.parseDouble(map.get("tipBalance").toString()));
		result.add(Double.parseDouble(map.get("total").toString()));
		return result;
	}
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
	public void buildRecord(WithdrawRecordBean wr) {
		        WithdrawRecord withdrawRecord=new WithdrawRecord();
		        withdrawRecord.setAccountNumber(wr.getAccountNumber());
		        withdrawRecord.setBrokerName(wr.getBrokerName());
		        withdrawRecord.setCreateTime(wr.getCreateTime());
		        withdrawRecord.setNum(wr.getNum());
		        withdrawRecord.setPopid(wr.getPopid());
		        withdrawRecord.setStatus(wr.getStatus());
		        withdrawRecord.setType(wr.getType());
		        withdrawRecord.setWithdrawOrderNo(wr.getWithdrawOrderNo());
//				String brokerName=brokerMapper.queryBrokerUserName(wr.getPopid());
//				wr.setBrokerName(brokerName);
				// 对经纪人钱包进行处理，把提现金额变成冻结金额
				// 计算应该扣除多少小费多少代购费，优先代购
				double num = wr.getNum();
				List<Double> balance = getBalance(wr.getPopid());
				double purchaseBalance = balance.get(0);
				double dPurchase = 0;
				double dTip = 0;
				if (num <= purchaseBalance) {
					dPurchase = num;
				} else {
					dPurchase = purchaseBalance;
					dTip = num - purchaseBalance;
				}
				Map<String, Object> m = new HashMap<String, Object>();
				m.put("popid", wr.getPopid());
				m.put("dPurchase", dPurchase);
				double tipBalance=dTip;
				if (tipBalance <= 0) {
					tipBalance= 0;
					withdrawRecord.setServiceAmount(0d);
				} else if (tipBalance>0&&tipBalance < 50) {
					tipBalance= tipBalance+5;
					withdrawRecord.setServiceAmount(5d);
				} else {
					tipBalance = tipBalance / 0.9;
					withdrawRecord.setServiceAmount(tipBalance*0.1);
				}
				m.put("dTip", tipBalance);
				Map<String, Object> logMap = new HashMap<String, Object>();
				logMap.put("purchaseAmount", Math.abs(dPurchase)*-1);
				logMap.put("tipAmount", Math.abs(tipBalance)*-1);
				logMap.put("changeDesc", "提现");
				logMap.put("brokerId",wr.getPopid());
				logMap.put("changeTime", time("yyyy-MM-dd HH:mm:ss"));
				logMap.put("orderNo", wr.getWithdrawOrderNo());
				walletMapper.frozenBrokerWallet(m);
				walletMapper.addBrokerWalletLog(logMap);
//				withdrawInvoke(wr);
				walletMapper.buildRecord(withdrawRecord);
	}

	public List<Map<String, Object>> chargeInDetails(Map<String, Object> param) {
		List<Map<String, Object>> l = walletMapper.chargeInDetails(param);
		if (l == null) {
			return new ArrayList<Map<String, Object>>();
		} else {
			return l;
		}
	}

	public double chargeInTotal(int popid) {
		return bigDecToDouble(walletMapper.chargeInTotal(popid));
	}

	public List<Map<String, Object>> buyDetails(Map<String, Object> param) {
		List<Map<String, Object>> l = walletMapper.buyDetails(param);
		if (l == null) {
			return new ArrayList<Map<String, Object>>();
		} else {
			return l;
		}
	}

	public double buyTotal(int popid) {
		return bigDecToDouble(walletMapper.buyTotal(popid));
	}

	public List<Map<String, Object>> allDetails(Map<String, Object> param) {
		List<Map<String, Object>> l = walletMapper.allDetails(param);
		if (l == null) {
			return new ArrayList<Map<String, Object>>();
		} else {
			return l;
		}
	}

	public double allTotal(int popid) {
		List<Double> balance = getBalance(popid);
		double purchaseBalance = balance.get(0);
		double tipBalance = balance.get(1);
		double total = purchaseBalance;
		if (tipBalance <= 5) {
			total += 0;
		} else if (tipBalance < 50) {
			total += (tipBalance - 5);
		} else {
			total += tipBalance * 0.9;
		}
		return total;
	}

	public Map<String, Object> myWallet(int popid) {
		double balance = allTotal(popid);// 可取余额
		double buyTotal = buyTotal(popid);// 代购总额
		double allTotal = chargeInTotal(popid);// 成交总额
		double inWithdraw = inWithdraw(popid);// 正在提现金额
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("popid", popid);
		m.put("date", "%" + sdf.format(new Date()) + "%");
		double todayTotal = bigDecToDouble(walletMapper.todayTotal(m));// 今日成交总额
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("balance", balance);
		result.put("buyTotal", buyTotal);
		result.put("allTotal", allTotal);
		result.put("inWithdraw", inWithdraw);
		result.put("todayTotal", todayTotal);
		return result;
	}

	public List<Map<String, Object>> withdrawDetails(Map<String, Object> param) {
		List<Map<String, Object>> l = walletMapper.withdrawDetails(param);
		if (l == null) {
			return new ArrayList<Map<String, Object>>();
		} else {
			return l;
		}
	}

	public double inWithdraw(int popid) {
		return bigDecToDouble(walletMapper.inWithdraw(popid));
	}

	/**
	 * 私有方法对mybatis返回的数据格式进行处理
	 * 
	 * @param o
	 *            bigDecimal类型对象
	 * @return
	 */
	private double bigDecToDouble(Object o) {
		if (o == null)
			return 0;
		else
			return Double.parseDouble(o.toString());
	}

	private int bigDecToInt(Object o) {
		if (o == null)
			return 0;
		else
			return (int) Double.parseDouble(o.toString());
	}

	private String time(String pattern) {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(new Date());
	}
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
	public void withdrawInvoke(WithdrawRecordBean wr) {
		// 对经纪人钱包进行处理，把提现金额变成冻结金额
		// 计算应该扣除多少小费多少代购费，优先代购
		double num = wr.getNum();
		List<Double> balance = getBalance(wr.getPopid());
		double purchaseBalance = balance.get(0);
		double dPurchase = 0;
		double dTip = 0;
		if (num <= purchaseBalance) {
			dPurchase = num;
		} else {
			dPurchase = purchaseBalance;
			dTip = num - purchaseBalance;
		}
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("popid", wr.getPopid());
		m.put("dPurchase", dPurchase);
		m.put("dTip", dTip);
		Map<String, Object> logMap = new HashMap<String, Object>();
		logMap.put("purchaseAmount", Math.abs(dPurchase)*-1);
		logMap.put("tipAmount", Math.abs(dTip)*-1);
		logMap.put("changeDesc", "提现");
		logMap.put("brokerId",wr.getPopid());
		logMap.put("changeTime", time("yyyy-MM-dd HH:mm:ss"));
		logMap.put("orderNo", wr.getWithdrawOrderNo());
		walletMapper.frozenBrokerWallet(m);
		walletMapper.addBrokerWalletLog(logMap);
	}

	public void buildPayRecord(Map<String, Object> param) {
		walletMapper.builePayRecord(param);
	}

	public int chargeInPage(Map<String, Object> param) {
		return bigDecToInt(walletMapper.chargeInPage(param));
	}

	public int buyPage(Map<String, Object> param) {
		return bigDecToInt(walletMapper.buyPage(param));
	}

	public int allPage(Map<String, Object> param) {
		return bigDecToInt(walletMapper.allPage(param));
	}

	public int withdrawPage(Map<String, Object> param) {
		return bigDecToInt(walletMapper.withdrawPage(param));
	}

	public void addBrokerWalletLog(Map<String, Object> param) {
		walletMapper.addBrokerWalletLog(param);
	}

	public void payToBroker(Map<String, Object> param) {
		walletMapper.payToBroker(param);
	}

	public void payToBrokerRecord(Map<String, Object> param) {
		walletMapper.addBrokerWalletLog(param);
	}

	public Map<String, Object> getPayOrderByNo(String orderNo) {
		return walletMapper.userOrderStatus(orderNo);
	}
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
	public void genBatchWithdrawOrder(String batchOrderNo,String pattern){
		logger.info("分批生成批量付款订单入参，batchOrderNo：{}，pattern：{}",batchOrderNo,pattern);
		Map<String,Object> queryParam=new HashMap<String, Object>();
		queryParam.put("time", time(pattern));
		queryParam.put("size", BATCH_NUM);
		List<Map<String,Object>> orders=walletMapper.queryWithdrawOrders(queryParam);
		List<Long> ids=new ArrayList<Long>();
		BigDecimal batchFee =new BigDecimal(0);
		for(Map<String,Object> order:orders){
			ids.add((Long)order.get("withdrawOrderId"));
			batchFee=batchFee.add((BigDecimal)order.get("withdrawAmount"));
		}
		int batchNum=ids.size();
		if(batchNum<1){
			return;
		}
		Map<String,Object> param=new HashMap<String, Object>();
		param.put("batchOrderNo", batchOrderNo);
		param.put("ids", ids);
		Map<String,Object> batchParam=new HashMap<String, Object>();
		Calendar createTime = Calendar.getInstance();
		Calendar latestTime = Calendar.getInstance();
		latestTime.add(Calendar.DAY_OF_MONTH, 2);
		batchParam.put("batchOrderNo", batchOrderNo);
		batchParam.put("batchFee", batchFee);
		batchParam.put("batchNum", batchNum);
		batchParam.put("createTime", createTime.getTime());
		batchParam.put("latestTime", latestTime.getTime());
		walletMapper.batchUpdateWithdrawOrder(param);
//		int j=1/0;
		walletMapper.insertBatchWithdrawOrder(batchParam);
		logger.info("分批生成批量付款订单岀参，batchFee：{}，batchNum：{}",batchFee,batchNum);
	}
	public void buildBatchWithdrawOrder(final String pattern){
//		new Thread(new Runnable() {
//			public void run() {
				logger.info("生成批量付款订单入参，pattern：{}",pattern);
				String time=time(pattern);
				int count =walletMapper.queryWithdrawOrderCount(time);
				int n = (count/BATCH_NUM)+1;//每100笔生成一笔批量付款订单
				for(int i=0;i<n;i++){
					String batchOrderNo = time("yyyyMMddHHmmss")+i;
					genBatchWithdrawOrder(batchOrderNo,pattern);
//					int j=1/0;
				}
				logger.info("生成批量付款订单岀参，count：{}",count);
//			}
//		}).start();
		
	}

	public void buildBatchWithdrawOrderBefore12() {
	}

	public void buildBatchWithdrawOrderAfter12() {
	}
	
	public static void main(String[] args) {
		List<Double> dTips=new ArrayList<Double>();
		dTips.add(-90d);
		dTips.add(-9d);
		dTips.add(0d);
		dTips.add(2d);
		dTips.add(9d);
		dTips.add(90d);
		for(double dTip:dTips){
			double tipBalance=dTip;
			if (tipBalance <= 5) {
				tipBalance= 5;
			} else if (tipBalance < 50) {
				tipBalance= tipBalance+5;
			} else {
				tipBalance = tipBalance / 0.9;
			}
			System.out.println(tipBalance);
		}
	}

	public int queryWithdrawOrderCount(String time) {
		return walletMapper.queryWithdrawOrderCount(time);
	}

	public List<WithdrawOrder> queryAliWithdrawOrdersByBatchOrderNo(
			String batchOrderNo) {
		return walletMapper.queryAliWithdrawOrderByBatchOrderNo(batchOrderNo);
	}

	public void dealWithAliBatchWithdrawResult(
			Map<String,WithdrawOrder> successMap,Map<String,WithdrawOrder> failMap, String batch_no) {
		
	}
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
	public void dealWithSuccessAliBatchWithdrawResult(
			Map<String, WithdrawOrder> successMap, String batch_no,String notify_id) {
		BatchWithdrawOrder batchOrder=walletMapper.queryBatchWithdrawOrderByOrderNo(batch_no);
		Map<Long,BigDecimal> moneyMap=new HashMap<Long, BigDecimal>();
		Map<Long,String> reasonMap=new HashMap<Long, String>();
		List<Long> orderIds=new ArrayList<Long>();
		List<Long> ids=new ArrayList<Long>();
		final List<Long> brokerids=new ArrayList<Long>();
		 
		for (Entry<String, WithdrawOrder> entry : successMap.entrySet()) {
			WithdrawOrder order=entry.getValue();
			if(order!=null){
				ids.add(order.getBrokerId());
				brokerids.add(order.getBrokerId());
				orderIds.add(order.getWithdrawOrderId());
				if(moneyMap.containsKey(order.getBrokerId())){
					moneyMap.put(order.getBrokerId(), moneyMap.get(order.getBrokerId()).add(order.getWithdrawAmount()).add(order.getServiceAmount()));
				}else{
					moneyMap.put(order.getBrokerId(), order.getWithdrawAmount().add(order.getServiceAmount()));
				}
				reasonMap.put(order.getWithdrawOrderId(), order.getReason());
			}
		}
		Map<String,Object> param=new HashMap<String, Object>();
		param.put("moneyMap", moneyMap);
		param.put("ids", ids);
		walletMapper.batchDeductBrokerWallet(param);//扣除冻结的钱
		
		Map<String,Object> orderParam=new HashMap<String, Object>();
		orderParam.put("status", 2);//表示提现成功
		orderParam.put("finishTime", Calendar.getInstance());
		orderParam.put("batchOrderId", batchOrder.getBatchOrderId());
		orderParam.put("ids", orderIds);
		orderParam.put("reasonMap", reasonMap);
		walletMapper.batchUpdateAliWithdrawOrder(orderParam);//更新支付订单状态
		
		Map<String,Object> batchMap=new HashMap<String, Object>();
		batchMap.put("status", 2);//已做回调处理
		batchMap.put("finishTime", Calendar.getInstance().getTime());
		batchMap.put("notifyId", notify_id);
		batchMap.put("batchOrderId", batchOrder.getBatchOrderId());
		walletMapper.updateBatchWithdrawOrder(batchMap);//更新批量付款订单状态
		
		//提现成功通知
		new Thread(new Runnable() {
			
			public void run() {
				for(Long brokerid:brokerids){
					//推送提现成功消息
					String isvAccountId= brokerMapper.queryBrokerIsvAccountId(brokerid.intValue());
					JPushClient client = JPush.getBrokerJPushClient();
					JPush.pushWithAlias(client, "提现成功，请到您的支付宝查收", isvAccountId);
					//记录消息
					Message message = new Message("提现成功，请到您的支付宝查收",brokerid.intValue(),MessageCons.USER_TYPE_BROKER,MessageCons.MESSAGE_TYPE_ORDER);
					message.setCreatetime(HelperUtil.getCurrentDate());
					message.setUpdatetime(HelperUtil.getCurrentDate());
					messageService.addMessage(message);
				}
			}
		}).start();
		
	}
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
	public void dealWithFailAliBatchWithdrawResult(
			Map<String, WithdrawOrder> failMap, String batch_no,String notify_id) {
		BatchWithdrawOrder batchOrder=walletMapper.queryBatchWithdrawOrderByOrderNo(batch_no);
		Map<String,Object> orderParam=new HashMap<String, Object>();
		Map<Long,String> reasonMap=new HashMap<Long, String>();
		List<Long> orderIds=new ArrayList<Long>();
		List<String> orderNos=new ArrayList<String>();
		for (Entry<String, WithdrawOrder> entry : failMap.entrySet()) {
			WithdrawOrder order=entry.getValue();
			if(order!=null){
				orderIds.add(order.getWithdrawOrderId());
				orderNos.add(order.getWithdrawOrderNo());
				reasonMap.put(order.getWithdrawOrderId(), order.getReason());
			}
		}
		
		Map<String,Object> queryMap=new HashMap<String, Object>();
		queryMap.put("orderNos", orderNos);
		List<BrokerWalletLog> logs=walletMapper.queryBrokerWalletLogsByOrderNo(queryMap);
		if(logs==null||logs.size()<0){//如果交易记录不存在拒绝处理
			return;
		}
		
		Map<String,Object> updateMap=new HashMap<String, Object>();
		Map<String,Object> insertParam=new HashMap<String, Object>();
		Map<Long,BigDecimal[]> addMap=new HashMap<Long,BigDecimal[]>();
		final List<Long> brokerids=new ArrayList<Long>();
		for(BrokerWalletLog log:logs){
			BigDecimal[] money =new BigDecimal[2];
			money[0]=log.getPurchaseAmount();
			money[1]=log.getTipAmount();
			if(addMap.containsKey(log.getBrokerId())){
				BigDecimal[] oldMoney=addMap.get(log.getBrokerId());
				oldMoney[0]=oldMoney[0].add(money[0]);
				oldMoney[1]=oldMoney[1].add(money[1]);
				addMap.put(log.getBrokerId(), oldMoney);
			}else{
				addMap.put(log.getBrokerId(), money);
				brokerids.add(log.getBrokerId());
			}
			
		}
		updateMap.put("addMap", addMap);
		insertParam.put("logs", logs);
		walletMapper.batchInsertBrokerWalletLog(insertParam);//生成钱包变化记录
		walletMapper.batchUpdateBrokerWallet(updateMap);//将冻结的钱转化为可取的代购金额和小费金额
		
		orderParam.put("status", 3);//表示提现失败
		orderParam.put("finishTime", Calendar.getInstance());
		orderParam.put("batchOrderId", batchOrder.getBatchOrderId());
		orderParam.put("ids", orderIds);
		orderParam.put("reasonMap", reasonMap);
		walletMapper.batchUpdateAliWithdrawOrder(orderParam);//更新支付订单状态
		
		Map<String,Object> batchMap=new HashMap<String, Object>();
		batchMap.put("status", 2);//已做回调处理
		batchMap.put("finishTime", Calendar.getInstance().getTime());
		batchMap.put("notifyId", notify_id);
		batchMap.put("batchOrderId", batchOrder.getBatchOrderId());
		walletMapper.updateBatchWithdrawOrder(batchMap);//更新批量付款订单状态
		
		//提现成功通知
				new Thread(new Runnable() {
					
					public void run() {
						for(Long brokerid:brokerids){
							//推送提现成功消息
							String isvAccountId= brokerMapper.queryBrokerIsvAccountId(brokerid.intValue());
							JPushClient client = JPush.getBrokerJPushClient();
							JPush.pushWithAlias(client, "尊敬的经纪人，您好，您的提现支付宝处理失败，提现金额已经回退到您的钱包，给您带来不便，非常抱歉", isvAccountId);
							//记录消息
							Message message = new Message("尊敬的经纪人，您好，您的提现支付宝处理失败，提现金额已经回退到您的钱包，给您带来不便，非常抱歉",brokerid.intValue(),MessageCons.USER_TYPE_BROKER,MessageCons.MESSAGE_TYPE_ORDER);
							message.setCreatetime(HelperUtil.getCurrentDate());
							message.setUpdatetime(HelperUtil.getCurrentDate());
							messageService.addMessage(message);
						}
					}
				}).start();
	}
}
